/**
 * 删除文件(夹): 异步,递归,可中断(可能已递归删除部分)
 * 		若同步/非递归/无中断: 使用$.fsRmf()/$.fsRmd()
 * @param path string|buffer 绝对路径 或 相对工作路径
 * @return Promise<boolean|null>  追加.stop()中断停止
 * 		boolean:原路径是否存在,  null:仅中断时
 */
$.fsRmx = function(path){
	const RD={encoding:'utf8',withFileTypes:true};
	const ERR = e=>{
		let x=e.code==='ENOENT'||e.code==='ENXIO';
		if(x) return true;  $.err('$.fsRmx',e);
	};
	const DEL = async (T,m)=>{
		if(m.isSymbolicLink() || !m.isDirectory())
			return $.fsAsync('unlink', m.full);
		const s = await $.fsAsync('readdir',m.full,RD);
		if(!T.X) return;  const F=m.full+'/', W=[];
		const B=v=>{ v.full=F+v.name; W.push(DEL(T,v)); };
		s.forEach(B);  await Promise.all(W);
		return T.X && $.fsAsync('rmdir',m.full);
	};
	$.fsRmx = function(path){
		const T = {X:true};
		const B=m=>DEL(T,m).then(()=>T.X).catch(e=>T.X&&ERR(e));
		let w = $.fsAsync('lstat',path).catch(e=>T.X&&!ERR(e));
		w=w.then(m=>T.X&&m&&B(m)); w.stop=()=>T.X=null; return w;
	};
	return $.fsRmx(path);
};
